package coint.btc.config.redis;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisConnectionException;

/**
 * 
 * @ClassName RedisRepository
 * @author BOOM
 * @date 2018/05/21
 *
 */
@Component
public class RedisRepository {

	@Autowired
	JedisConnectionFactory jedisConnectionFactory;
	
	private static Jedis jedis = null;
	
	final private static String PONG = "PONG";
	
	/**
	 * 服务器启动验证redis连接池是否正常
	 */
	@PostConstruct
	public void initRedis() {
		jedis = getJedis();
		String ping = jedis.ping();
		if (!PONG.equals(ping)) {
			System.exit(0);
		}
		close();
		System.out.println("redis初始化成功");
	}
	
	/**
	 * 从redis连接池中获取redis连接
	 * @return
	 */
	public synchronized Jedis getJedis() {
		return jedisConnectionFactory.getShardInfo().createResource();
	}
	
	/**
	 * 释放redis连接
	 * 注：这里不是关闭redis，而是释放连接到连接池
	 */
	public void close() {
		if(jedis != null) {
			jedis.close();
		}
		jedis = null;
	}
	
	/**
	 * 添加key value
	 * 
	 * @param dbIndex
	 * @param key
	 * @param value
	 */
	public synchronized <V> void set(int dbIndex, String key, V value) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		jedis.select(dbIndex);
		jedis.set(key, JSON.toJSONString(value));
		close();
	}

	/**
	 * 添加key value 并设置时间
	 * 
	 * @param dbIndex
	 * @param key
	 * @param value
	 * @param seconds
	 */
	public synchronized <V> void set(int dbIndex, String key, V value, int seconds) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		jedis.select(dbIndex);
		jedis.setex(key, seconds, JSON.toJSONString(value));
		close();
	}

	/**
	 * 删除key
	 * 
	 * @param key
	 * @param dbIndex
	 */
	public synchronized void del(String key, int dbIndex) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		jedis.select(dbIndex);
		jedis.del(key);
		close();
	}

	/**
	 * 获取key
	 * 
	 * @param key
	 * @param dbIndex
	 * @param clz
	 * @return
	 */
	public synchronized <V> V get(String key, int dbIndex, Class<V> clazz) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		jedis.select(dbIndex);
		String string = jedis.get(key);
		close();
		if(string == null) {
			return null;
		}
		return JSON.parseObject(string, clazz);
	}

	/**
	 * 添加hash key value
	 * 
	 * @param dbIndex
	 * @param hash
	 * @param key
	 * @param value
	 */
	public synchronized <V> void hset(int dbIndex, String hash, String key, V value) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		jedis.select(dbIndex);
		jedis.hset(hash, key, JSON.toJSONString(value));
		close();
	}

	/**
	 * 删除hash key value
	 * 
	 * @param dbIndex
	 * @param hash
	 * @param key
	 */
	public synchronized void hdel(int dbIndex, String hash, String key) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		jedis.select(dbIndex);
		jedis.hdel(hash, key);
		close();
	}

	/**
	 * 获取hash key value
	 * 
	 * @param hash
	 * @param key
	 * @param dbIndex
	 * @param clz
	 * @return
	 */
	public synchronized <V> V hget(String hash, String key, int dbIndex, Class<V> clazz) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		jedis.select(dbIndex);
		String hget = jedis.hget(hash, key);
		close();
		if(hget == null) {
			return null;
		}
		return JSON.parseObject(hget, clazz);
	}

	/**
	 * 获取hash 所有
	 * 
	 * @param hash
	 * @param dbIndex
	 * @param clz
	 * @return
	 */
	public synchronized <V> Map<String, V> hgetAll(String hash, int dbIndex, Class<V> clazz) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		jedis.select(dbIndex);
		Map<String, String> hgetAll = jedis.hgetAll(hash);
		close();
		Map<String, V> map = new HashMap<String, V>(hgetAll.size());
		for (Map.Entry<String, String> entry : hgetAll.entrySet()) {
			map.put(entry.getKey(), JSON.parseObject(entry.getValue(), clazz));
		}
		return map;
	}

	/**
	 * 添加key list
	 * 
	 * @param key
	 * @param list
	 */
	public synchronized <V> void lset(String key, List<V> list) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		list.forEach(obj -> {
			jedis.lpush(key, JSON.toJSONString(obj));
		});
		close();
	}

	/**
	 * 获取key list
	 * 
	 * @param key
	 * @param clz
	 * @return
	 */
	public synchronized <V> List<V> lget(String key, Class<V> clazz) {
		try {
			jedis = getJedis();
		} catch (JedisConnectionException e) {
			throw new JedisConnectionException("redis连接超时");
		}
		List<String> lrange = jedis.lrange(key, 0, -1);
		List<V> list = new ArrayList<V>();
		lrange.forEach(str -> {
			list.add(JSON.parseObject(str, clazz));
		});
		return list;
	}
}
